#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include "sys/err.h"
#include "apitrans.h"
#include "crypto.h"

extern sys_apitrans_t sysapi;



/* Single-key DES key schedule */
int deskey(uint8_t key[8], int decrypt)
{
    int (*pdeskey)(uint8_t key[8], int decrypt);
    pdeskey = sysapi(DESKEY_API);
    if (pdeskey) {
        return pdeskey(key, decrypt);
    }
    return -API_UNSUPPORTED_ERR;
}
int des(uint8_t block[8], uint8_t output[8])
{
    int (*pdes)(uint8_t block[8], uint8_t output[8]);
    pdes = sysapi(DES_API);
    if (pdes) {
        return pdes(block, output);
    }
    return -API_UNSUPPORTED_ERR;
}

/* Triple-DES key schedule */
int des3key2(uint8_t key[16], int decrypt)
{
    int (*pdes3key2)(uint8_t key[16], int decrypt);
    pdes3key2 = sysapi(DES3KEY2_API);
    if (pdes3key2) {
        return pdes3key2(key, decrypt);
    }
    return -API_UNSUPPORTED_ERR;
}
int des3key3(uint8_t key[24], int decrypt)
{
    int (*pdes3key3)(uint8_t key[24], int decrypt);
    pdes3key3 = sysapi(DES3KEY3_API);
    if (pdes3key3) {
        return pdes3key3(key, decrypt);
    }
    return -API_UNSUPPORTED_ERR;
}
int des3(uint8_t block[8], uint8_t output[8])
{
    int (*pdes3)(uint8_t block[8], uint8_t output[8]);
    pdes3 = sysapi(DES3_API);
    if (pdes3) {
        return pdes3(block, output);
    }
    return -API_UNSUPPORTED_ERR;
}

uint8_t rng_get_byte(void)
{
    uint8_t (*prng_get_byte)(void);
    prng_get_byte = sysapi(RNG_GET_BYTE_API);
    if (prng_get_byte) {
        return prng_get_byte();
    }
    return 0;
}
int rng_get_string(uint8_t * buf, uint32_t len)
{
    int (*prng_get_string)(uint8_t * buf, uint32_t len);
    prng_get_string = sysapi(RNG_GET_STRING_API);
    if (prng_get_string) {
        return prng_get_string(buf, len);
    }
    return -API_UNSUPPORTED_ERR;
}

uint16_t crc16(uint16_t crc, uint8_t *buffer, uint32_t len)
{
    uint16_t (*pcrc16)(uint16_t crc, uint8_t *buffer, uint32_t len);
    pcrc16 = sysapi(CRC16_API);
    if (pcrc16) {
        return pcrc16(crc,buffer, len);
    }
    return -API_UNSUPPORTED_ERR;
}

uint16_t crc16_itu_t(uint16_t crc, uint8_t *buffer, uint32_t len)
{
    uint16_t (*pcrc16_itu_t)(uint16_t crc, uint8_t *buffer, uint32_t len);
    pcrc16_itu_t = sysapi(CRC16_ITU_T_API);
    if (pcrc16_itu_t) {
        return pcrc16_itu_t(crc,buffer, len);
    }
    return -API_UNSUPPORTED_ERR;

}


int sha2_starts(int is224)
{
    int (*psha2_starts)(int is224);
    psha2_starts = sysapi(SHA2_STARTS_API);
    if (psha2_starts) {
        return psha2_starts(is224);
    }
    return -API_UNSUPPORTED_ERR;
}
void sha2_update(uint8_t * input, uint32_t length)
{
    void (*psha2_update)(uint8_t * input, uint32_t length);
    psha2_update = sysapi(SHA2_UPDATE_API);
    if (psha2_update) {
        psha2_update(input, length);
    }
}


void sha2_finish(uint8_t digest[32])
{
    void (*psha2_finish)(uint8_t digest[32]);
    psha2_finish = sysapi(SHA2_FINISH_API);
    if (psha2_finish) {
        psha2_finish(digest);
    }
}
void sha1_starts( void )
{
    void (*psha1_starts)( void );
    psha1_starts = sysapi(SHA1_STARTS_API);
    if (psha1_starts) {
        psha1_starts();
    }
}

void sha1_update (unsigned char *input, int ilen)
{
    void (*psha1_update)(unsigned char *input, int ilen);
    psha1_update = sysapi(SHA1_UPDATE_API);
    if (psha1_update) {
        psha1_update(input, ilen);
    }

}

void sha1_finish (unsigned char output[20])
{
    void (*psha1_finish)(unsigned char output[20]);
    psha1_finish = sysapi(SHA1_FINISH_API);
    if (psha1_finish) {
        psha1_finish(output);
    }

}

int rsapublicfunc(uint8_t *output,uint32_t *outputLen,
                uint8_t *input, uint32_t inputLen,R_RSA_PUBLIC_KEY *publicKey )
{
    int (*prsapublicfunc)(uint8_t *output,uint32_t *outputLen,
                    uint8_t *input, uint32_t inputLen,R_RSA_PUBLIC_KEY *publicKey );
    
    prsapublicfunc = sysapi(RSAPUBLICFUNC_API);
    if (prsapublicfunc) {
        return prsapublicfunc(output, outputLen, input, inputLen, publicKey);
    }
    return -API_UNSUPPORTED_ERR;
}


